#pragma once

#include <mutex>
#include <queue>
#include <condition_variable>
using namespace std;

template<class T>
class BlockQueue
{
    #define QUEUE_SIZE 5
public:
    BlockQueue(size_t size = QUEUE_SIZE):_size(size)
    {}
    ~BlockQueue()
    {}

    void Push(const T& val)
    {
        unique_lock<mutex> lck(_mutex);
        while(q.size() == _size)
        {
            _pro_cond.wait(lck);
        }
        q.push(val);
        _com_cond.notify_one();
    }

    void Pop(T* val)
    {
        unique_lock<mutex> lck(_mutex);
        while(q.size() == 0)
        {
            _com_cond.wait(lck);
        }
        *val = q.front(); q.pop();
        _pro_cond.notify_one();
    }
private:
    queue<T> q;
    mutex _mutex;
    condition_variable _pro_cond;
    condition_variable _com_cond;
    size_t _size;
};